home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
tde11.arc
/
ED.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-06
|
41KB
|
1,360 lines
/******************* start of original comments ********************/
/*
* Written by Douglas Thomson (1989/1990)
*
* This source code is released into the public domain.
*/
/*
* Name: dte - Doug's Text Editor program - main editor module
* Purpose: This file contains the main editor module, and a number of the
* smaller miscellaneous editing commands.
* It also contains the code for dispatching commands.
* File: ed.c
* Author: Douglas Thomson
* System: this file is intended to be system-independent
* Date: October 1, 1989
* I/O: file being edited
* files read or written
* user commands and prompts
* Notes: see the file "dte.doc" for general program documentation
*/
/********************* end of original comments ********************/
/*
* The basic editor routines have been EXTENSIVELY reworked. I have added
* support for lines longer than 80 columns and I have added line number
* support. I like to know the real line number that editor functions are
* working on and I like to know the total number of lines in a file.
*
* I rewrote the big series of ifs in the dispatch subroutine. It is now
* a series of case statements. By doing so, it should be easier to implement a
* configuration file later on.
*
* I added a few functions that I use quite often and I deleted a few that I
* rarely use. Added are Split Line, Join Line, and Duplicate Line. Deleted
* are Word Delete, Goto Marker 0-9 (others?).
*
* I felt that the insert routine should be separated into two routines. One
* for inserting the various combinations of newlines and one for inserting
* 'regular' text characters.
*
* One of Doug's design considerations was keeping screen updates to a minimum.
* I have expanded upon that idea and added support for updating windows
* LOCALly, GLOBALly, or NOT_LOCALly. For example, scrolling in one window
* does not affect the text in another window - LOCAL update. Adding, deleting,
* or modifying text in one window may affect text in other windows - GLOBAL
* update. Sometimes, updates to the current window are handled in the task
* routines so updates to other windows are done NOT_LOCALly.
*
* Also note that using functions copy_line and un_copy_line to change a line
* automatically adjusts the g_status.end_mem pointer. If a function bypasses
* those functions, adjusting the g_status.end_mem pointer must be done
* explicitly.
*
* New editor name: tde, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991
*
* This modification of Douglas Thomson's code is released into the
* public domain, Frank Davis. You may distribute it freely.
*/
#include "tdestr.h" /* global variables */
#include "global.h" /* global variables */
#include "define.h"
#include "tdefunc.h"
/*
* Name: tab_key
* Purpose: To make the necessary changes after the user types the tab key.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If in insert mode, then this function adds the required
* number of spaces in the file.
* If not in insert mode, then tab simply moves the cursor right
* the required distance.
*/
void tab_key( window )
windows *window;
{
int spaces; /* the spaces to move to the next tab stop */
text_ptr source; /* source for block move to make room for c */
text_ptr dest; /* destination for block move */
long number; /* number of characters to be moved */
int space, pad, add, len, i, rcol, ccol;
file_infos *file;
int prompt_line;
prompt_line = window->bottom_line;
rcol = window->rcol;
ccol = window->ccol;
/*
* work out the number of spaces to the next tab stop
*/
spaces = g_status.tab_size - (rcol % g_status.tab_size);
if (g_status.insert && rcol + spaces < g_display.line_length) {
copy_line( window->cursor, prompt_line );
/*
* work out how many characters need to be inserted
*/
len = linelen( g_status.line_buff );
if (rcol > len) /* padding required */
pad = rcol - len;
else
pad = 0;
if (g_status.line_buff[len] == CONTROL_Z)
++pad;
if (len + pad + spaces >= g_display.line_length)
error( WARNING, window->bottom_line, "line too long to add" );
else {
file = window->file_info;
space = 0;
if (pad > 0 || spaces > 0) {
space = pad + spaces;
if (g_status.line_buff[len] == CONTROL_Z) {
g_status.line_buff[len] = '\n';
g_status.line_buff[len+1] = CONTROL_Z;
++file->length;
show_size( window );
--pad;
++len;
}
source = g_status.line_buff + rcol - pad;
dest = source + pad + spaces;
len = len + pad - rcol + 2;
memmove( dest, source, len );
/*
* if padding was required, then put in the required spaces
*/
for (i=pad; i>0; i--)
*source++ = ' ';
for (i=spaces; i>0; i--)
*source++ = ' ';
}
file->dirty = GLOBAL;
show_changed_line( window );
rcol += spaces;
ccol += spaces;
}
} else if (rcol + spaces <= g_display.line_length) {
/*
* advance the cursor without changing the text underneath
*/
rcol += spaces;
ccol += spaces;
}
check_virtual_col( window, rcol, ccol );
}
/*
* Name: insert_newline
* Purpose: insert a newline
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* carriage_return: TRUE if carriage return, FALSE if insert line
* split_line: TRUE if split line, FALSE otherwise
*/
void insert_newline( window, carriage_return, split_line )
windows *window;
int carriage_return, split_line;
{
text_ptr source; /* source for block move to make room for c */
text_ptr dest; /* destination for block move */
long number; /* number of characters to be moved */
int len; /* length of current line */
int pad; /* padding to add if cursor beyond end of line */
int add; /* characters to be added (usually 1 in insert mode) */
int i; /* counter for adding autoindenting */
int rcol;
text_ptr prev; /* previous lines scanned for autoindent */
int space;
char *trail_space;
file_infos *file;
int prompt_line;
prompt_line = window->bottom_line;
file = window->file_info;
window->cursor = cpf( window->cursor );
copy_line( window->cursor, prompt_line );
len = linelen( g_status.line_buff );
source = g_status.line_buff + len;
if (carriage_return || split_line) {
if (window->rcol < len)
source = g_status.line_buff + window->rcol;
}
/*
* make room for '\n' just after source (source+1)
*/
memmove( source+1, source, linelen( source )+2 );
*source = '\n';
un_copy_line( window->cursor, window, TRUE );
adjust_windows_cursor( window, 1 );
if (carriage_return || split_line)
update_line( window );
if (window->cline == window->bottom_line)
window_scroll_up( window->top_line, window->bottom_line );
else
window_scroll_down( window->cline+1, window->bottom_line );
/*
* If the cursor is to move down to the next line, then update
* the line and column appropriately.
*/
file->dirty = NOT_LOCAL;
if (carriage_return || split_line) {
window->cursor = find_next( window->cursor );
if (window->cline < window->bottom_line)
window->cline++;
window->rline++;
rcol = window->rcol;
/*
* indentation is only required if we are in the right mode,
* the user typed <CR>, and if there is not space followed
* by something after the cursor.
*/
if (g_status.indent) {
/*
* autoindentation is required. Match the indentation of
* the first line above that is not blank.
*/
add = first_non_blank( g_status.line_buff );
if (g_status.line_buff[add] == '\n' ||
g_status.line_buff[add] == CONTROL_Z) {
prev = cpb( window->cursor );
while ((prev = find_prev( prev )) != NULL) {
add = first_non_blank( (char *)prev );
if (prev[add] != '\n')
break;
}
}
copy_line( window->cursor, prompt_line );
len = linelen( g_status.line_buff );
source = g_status.line_buff;
dest = source + add;
memmove( dest, source, len+add+2 );
/*
* now put in the autoindent characters
*/
for (i=add; i>0; i--)
*source++ = ' ';
window->rcol = add;
un_copy_line( window->cursor, window, TRUE );
update_line( window );
} else
window->rcol = 0;
if (split_line) {
window->cursor = cpb( window->cursor );
window->cursor = find_prev( window->cursor );
if (window->cline > window->top_line)
window->cline--;
window->rline--;
window->rcol = rcol;
}
check_virtual_col( window, window->rcol, window->ccol );
if (file->dirty)
file->dirty = GLOBAL;
}
/*
* record that file has been modified
*/
++file->length;
restore_marked_block( window, 1 );
show_size( window );
}
/*
* Name: insert_overwrite
* Purpose: To make the necessary changes after the user has typed a normal
* printable character
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* c: the character just typed
*/
void insert_overwrite( window, c )
windows *window;
int c;
{
text_ptr source; /* source for block move to make room for c */
text_ptr dest; /* destination for block move */
long number; /* number of characters to be moved */
int len; /* length of current line */
int pad; /* padding to add if cursor beyond end of line */
int i;
int add; /* characters to be added (usually 1 in insert mode) */
int line; /* line on screen to save and show prompt */
int space, rcol, ccol;
file_infos *file;
line = window->bottom_line;
rcol = window->rcol;
ccol = window->ccol;
/*
* first check we have room - the editor can not
* cope with lines wider than g_display.line_length
*/
if (rcol >= g_display.line_length)
error( WARNING, line, "cannot insert more characters" );
else {
file = window->file_info;
copy_line( window->cursor, line );
/*
* work out how many characters need to be inserted
*/
len = linelen( g_status.line_buff );
if (rcol > len) /* padding required */
pad = rcol - len;
else
pad = 0;
/*
* if this is the last line in a file, the last character in the
* line buffer will be CONTROL_Z. increment pad and insert a \n.
*/
if (g_status.line_buff[len] == CONTROL_Z)
++pad;
if (g_status.insert || rcol >= len)
/*
* inserted characters, or overwritten characters at the end of
* the line, are inserted.
*/
add = 1;
else
/*
* and no extra space is required to overwrite existing characters
*/
add = 0;
/*
* check that current line would not get too long. Note that there must
* be space for both the old line and any indentation.
*/
if (len + pad + add >= g_display.line_length)
error( WARNING, line, "no more room to add" );
else {
/*
* all clear to add new character!
*/
/*
* move character to make room for whatever needs to be inserted
*/
space = 0;
if (pad > 0 || add > 0) {
space = pad + add;
if (g_status.line_buff[len] == CONTROL_Z) {
if (rcol > len) {
g_status.line_buff[rcol+1] = '\n';
g_status.line_buff[rcol+2] = CONTROL_Z;
} else {
g_status.line_buff[len] = '\n';
g_status.line_buff[len+1] = CONTROL_Z;
}
++file->length;
show_size( window );
--pad;
++len;
}
source = g_status.line_buff + rcol - pad;
dest = source + pad + add;
len = len + pad - rcol + 2;
memmove( dest, source, len );
/*
* if padding was required, then put in the required spaces
*/
for (i=pad; i>0; i--)
*source++ = ' ';
} else
source = g_status.line_buff + rcol;
/*
* now place the new character
*/
*source = c;
/*
* if we added anything, show the changed line.
*/
if (pad > 0 || add > 0)
update_line( window );
else
update_char( window, c, ccol, window->cline );
/*
* always increment the real column (rcol) and adjust the
* logical and base column as needed.
*/
file->dirty = GLOBAL;
if (ccol < g_display.ncols - 1) {
ccol++;
show_changed_line( window );
} else
window->bcol++;
rcol++;
/*
* record that file has been modified and adjust cursors and
* file start and end markers as needed.
*/
}
window->rcol = rcol;
window->ccol = ccol;
}
}
/*
* Name: join_line
* Purpose: To join current line and line below at cursor
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: trunc the line then join with line below if it exists
*/
void join_line( window )
windows *window;
{
int len; /* length of current line */
text_ptr source; /* source for block move to delete word */
text_ptr dest; /* destination for block move */
long number; /* number of characters to move */
int del_len; /* number of characters to delete */
text_ptr p; /* next line in file */
int pad, i; /* padding spaces required */
int cr; /* does current line end with carriage return? */
int line; /* line on screen to save and show prompt */
file_infos *file;
int rcol;
file = window->file_info;
line = window->bottom_line;
rcol = window->rcol;
window->cursor = cpf( window->cursor );
copy_line( window->cursor, window->bottom_line );
if (rcol < (len = linelen( g_status.line_buff ))) {
/*
* delete rest of line
*/
dest = g_status.line_buff + rcol;
/*
* the \n at the end of the line must NOT be deleted
*/
if (g_status.line_buff[len] == '\n')
*dest++ = '\n';
len = find_CONTROL_Z( dest );
*dest = CONTROL_Z;
un_copy_line( window->cursor, window, FALSE );
file->dirty = GLOBAL;
}
/*
* we need to combine with the next line, if any
*/
if ((p = find_next( window->cursor )) != NULL) {
/*
* add padding if required
*/
len = linelen( g_status.line_buff );
if (g_status.line_buff[len] == '\n')
cr = 1;
else
cr = 0;
if (rcol > len)
pad = rcol - len;
else
pad = 0;
/*
* check room to combine lines
*/
if (len + pad + cr + linelen( p ) >= g_display.line_length)
error( WARNING, line, "cannot combine lines" );
else {
/*
* do the move
*/
source = g_status.line_buff + rcol - pad;
dest = source + pad;
len = len + pad - rcol + 1 + cr;
memmove( dest, source, len );
/*
* insert the padding
*/
for (i=pad; i>0; i--)
*source++ = ' ';
/*
* remove the \n separating the two lines.
*/
i = 0;
if (*source == '\n') {
*source = CONTROL_Z;
i = -1;
}
g_status.copied = TRUE;
un_copy_line( window->cursor, window, FALSE );
adjust_windows_cursor( window, i );
--file->length;
restore_marked_block( window, -1 );
show_size( window );
file->dirty = GLOBAL;
}
}
}
/*
* Name: dup_line
* Purpose: Duplicate current line
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: cursor stays on current line
*/
void dup_line( window )
windows *window;
{
int len, i; /* length of current line */
int line; /* line on screen to save and show prompt */
long number;
file_infos *file;
text_ptr d, s;
line = window->bottom_line;
window->cursor = cpf( window->cursor );
un_copy_line( window->cursor, window, TRUE );
/*
* don't dup the ^Z or a NULL line
*/
if (*window->cursor != CONTROL_Z && (d=find_next( window->cursor )) !=NULL) {
file = window->file_info;
/*
* don't use buffers to dup the line. use hw_move to make space and
* copy current line at same time. d is set to beginning of next line.
*/
s = window->cursor;
len = linelen( s );
if (s[len] == '\n')
++len;
number = ptoul( g_status.end_mem ) - ptoul( s );
hw_move( d, s, number );
g_status.end_mem = addltop( len, g_status.end_mem );
adjust_start_end( file, len );
addorsub_all_cursors( window, len );
adjust_windows_cursor( window, 1 );
/*
* if current line is the bottom line, we can't see the dup line because
* cursor doesn't move and dup line is added after current line.
*/
if (window->cline != line) {
window_scroll_down( window->cline, line );
update_line( window );
}
file->dirty = NOT_LOCAL;
/*
* record that file has been modified
*/
file->modified = TRUE;
++file->length;
restore_marked_block( window, 1 );
show_size( window );
show_avail_mem( );
} else
error( WARNING, line, "cannot duplicate line" );
}
/*
* Name: back_space
* Purpose: To delete the character to the left of the cursor.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is at the left of the line, then combine the
* current line with the previous one.
* If in indent mode, and the cursor is on the first non-blank
* character of the line, then match the indentation of an
* earlier line.
*/
void back_space( window )
windows *window;
{
int len; /* length of the current line */
text_ptr source; /* source of block move to delete character */
text_ptr dest; /* destination of block move */
long number; /* number of characters to move */
text_ptr p; /* previous line in file */
int cr; /* did line end with carriage return? */
int plen; /* length of previous line */
int del_count; /* number of characters to delete */
int pos; /* the position of the first non-blank char */
int prompt_line; /* line on screen to save and show prompt */
int rcol, ccol, ncols;
file_infos *file;
file = window->file_info;
prompt_line = window->bottom_line;
copy_line( window->cursor, prompt_line );
len = linelen( g_status.line_buff );
rcol = window->rcol;
ccol = window->ccol;
ncols = g_display.ncols;
if (rcol == 0) {
/*
* combine this line with the previous, if any
*/
window->cursor = cpb( window->cursor );
if ((p = find_prev( window->cursor )) != NULL) {
if (len + 2 + (plen = linelen( p )) >= g_display.line_length) {
error( WARNING, prompt_line, "cannot combine lines" );
return;
}
un_copy_line( window->cursor, window, TRUE );
copy_line( p, prompt_line );
g_status.line_buff[plen] = CONTROL_Z;
window->cursor = p;
un_copy_line( window->cursor, window, FALSE );
/*
* make sure cursor stays on the screen, at the end of the
* previous line
*/
if (window->cline > window->top_line)
--window->cline;
--window->rline;
rcol = plen;
ccol = rcol - window->bcol;
--file->length;
restore_marked_block( window, -1 );
adjust_windows_cursor( window, -1 );
show_size( window );
check_virtual_col( window, rcol, ccol );
file->dirty = GLOBAL;
}
} else {
/*
* normal delete
*
* find out how much to delete (depends on indent mode)
*/
del_count = 1; /* the default */
if (g_status.indent) {
/*
* indent only happens if the cursor is on the first
* non-blank character of the line
*/
if ((pos = first_non_blank( g_status.line_buff )) == rcol
|| g_status.line_buff[pos] == '\n'
|| g_status.line_buff[pos] == CONTROL_Z) {
/*
* now work out how much to indent
*/
p = cpb( window->cursor );
for (p=find_prev( p ); p != NULL; p=find_prev( p )) {
if ((plen = first_non_blank( (char *)p )) < rcol &&
*(p+plen) != '\n') {
/*
* found the line to match
*/
del_count = rcol - plen;
break;
}
}
}
}
/*
* move text to delete char(s), unless no chars actually there
*/
if (rcol - del_count < len) {
dest = g_status.line_buff + rcol - del_count;
if (rcol > len) {
source = g_status.line_buff + len;
len = 2;
} else {
source = g_status.line_buff + rcol;
len = len - rcol + 2;
}
memmove( dest, source, len );
}
rcol -= del_count;
ccol -= del_count;
check_virtual_col( window, rcol, ccol );
if (file->dirty) {
display_current_window( window );
file->dirty = NOT_LOCAL;
} else
file->dirty = GLOBAL;
show_changed_line( window );
}
file->modified = TRUE;
}
/*
* Name: line_kill
* Purpose: To delete the line the cursor is on.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If *window->cursor is pointing to CONTROL_Z then do not do a
* line kill (can't kill a NULL line).
*/
void line_kill( window )
windows *window;
{
int i = 0;
text_ptr s; /* next line in file */
windows w;
file_infos *file;
file = window->file_info;
if (file->length > 0 && *window->cursor != CONTROL_Z) {
g_status.copied = TRUE;
g_status.line_buff[0] = CONTROL_Z;
s = window->cursor = cpf( window->cursor );
/*
* if line to delete has \n at end of line then decrement file length.
*/
if (*(s + linelen( s )) == '\n') {
--file->length;
--i;
}
un_copy_line( s, window, FALSE );
file->dirty = NOT_LOCAL;
/*
* move all cursors one according to i, restore begin and end block
*/
adjust_windows_cursor( window, i );
restore_marked_block( window, i );
/*
* we are not doing a GLOBAL update, so update current window here
*/
if (file->dirty == NOT_LOCAL) {
window_scroll_up( window->cline, window->bottom_line );
dup_window_info( &w, window );
for (; w.cursor != NULL; w.cline++, w.rline++) {
if (w.cline == w.bottom_line) {
update_line( &w );
break;
}
w.cursor = find_next( w.cursor );
}
}
show_size( window );
}
}
/*
* Name: char_del_under
* Purpose: To delete the character under the cursor.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is beyond the end of the line, then this
* command is ignored.
*/
void char_del_under( window )
windows *window;
{
text_ptr source; /* source of block move to delete character */
int len;
int rcol;
copy_line( window->cursor, window->bottom_line );
rcol = window->rcol;
if (rcol < (len = linelen( g_status.line_buff ))) {
/*
* move text to delete char using buffer
*/
source = g_status.line_buff + rcol + 1;
memmove( source-1, source, len-rcol+2 );
window->file_info->dirty = GLOBAL;
show_changed_line( window );
}
}
/*
* Name: eol_kill
* Purpose: To delete everything from the cursor to the end of the line.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is beyond the end of the line, then this
* command is ignored.
*/
void eol_kill( window )
windows *window;
{
char *dest; /* the start of the delete area */
copy_line( window->cursor, window->bottom_line );
if (window->rcol < linelen( g_status.line_buff )) {
/*
* truncate to delete rest of line
*/
dest = g_status.line_buff + window->rcol;
*dest++ = '\n';
*dest = CONTROL_Z;
window->file_info->dirty = GLOBAL;
show_changed_line( window );
}
}
/*
* Name: undo_line
* Purpose: To retrieve unaltered line if possible.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Changes are made to the line buffer so the underlying text has
* not changed. put the unchanged line in the line buffer.
*/
void undo_line( window )
windows *window;
{
if (g_status.copied) {
g_status.copied = FALSE;
copy_line( window->cursor, window->bottom_line );
window->file_info->dirty = GLOBAL;
show_changed_line( window );
}
}
/*
* Name: goto_left
* Purpose: To move the cursor to the left of the current line.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
*/
void goto_left( window )
windows *window;
{
int rcol;
if (g_status.copied)
rcol = first_non_blank( g_status.line_buff );
else
rcol = first_non_blank( window->cursor );
if (window->cursor[rcol] == '\n')
rcol = 0;
check_virtual_col( window, rcol, window->ccol );
}
/*
* Name: goto_right
* Purpose: To move the cursor to the right of the current line.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
*/
void goto_right( window )
windows *window;
{
int rcol;
if (g_status.copied)
rcol = linelen( g_status.line_buff );
else
rcol = linelen( window->cursor );
window->ccol = rcol - window->bcol;
check_virtual_col( window, rcol, window->ccol );
}
/*
* Name: goto_top
* Purpose: To move the cursor to the top of the current window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the start of the file occurs before the top of the window,
* then the start of the file is moved to the top of the window.
*/
void goto_top( window )
windows *window;
{
text_ptr cursor; /* anticipated cursor line */
un_copy_line( window->cursor, window, TRUE );
window->cursor = cpb( window->cursor );
for (; window->cline > window->top_line; window->cline--,window->rline--) {
if ((cursor = find_prev( window->cursor )) == NULL)
break;
window->cursor = cursor;
}
}
/*
* Name: goto_bottom
* Purpose: To move the cursor to the bottom of the current window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
*/
void goto_bottom( window )
windows *window;
{
text_ptr cursor;
un_copy_line( window->cursor, window, TRUE );
window->cursor = cpf( window->cursor );
for (; window->cline < window->bottom_line; window->cline++,window->rline++) {
if ((cursor = find_next( window->cursor )) == NULL)
break;
window->cursor = cursor;
}
}
/*
* Name: set_tabstop
* Purpose: To set the current interval between tab stops
* Date: October 1, 1989
* Notes: Tab interval must be reasonable, and this function will
* not allow tabs more than MAX_COLS / 2.
*/
void set_tabstop( line )
int line;
{
char num_str[MAX_COLS]; /* tab interval as a character string */
int tab; /* new tab interval */
int rc;
rc = OK;
while (rc == OK) {
itoa( g_status.tab_size, num_str, 10 );
rc = get_name( "Tab interval: ", line, num_str, g_display.message_color );
if (rc == OK) {
tab = atoi( num_str );
if (tab < MAX_COLS/2) {
g_status.tab_size = tab;
rc = ERROR;
} else
error( WARNING, line, "tab size too long" );
}
}
}
/*
* Name: show_line_col
* Purpose: show current real line and column of current cursor position
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Blank old position and display new position. current line and
* column may take up to 12 columns, which allows the display of
* 999 columns and 99,999,999 lines.
*/
void show_line_col( windows *window )
{
int i, k, pline;
char line_col[20], num[10];
/*
* blank out current line:column position.
*/
strcpy( line_col, " " );
/*
* convert column to ascii and store in display buffer.
*/
itoa( window->rcol+1, num, 10 );
i = strlen( num ) - 1;
for (k=11; i>=0; i--, k--)
line_col[k] = num[i];
/*
* put in colon to separate line and column
*/
line_col[k--] = ':';
/*
* convert line to ascii and store in display buffer.
*/
ltoa( window->rline, num, 10 );
i = strlen( num ) - 1;
for (; i>=0; i--, k--)
line_col[k] = num[i];
/*
* find line to start line:column display then output
*/
pline = window->top_line - 1;
s_output( line_col, pline, MAX_COLS-12, g_display.head_color );
}
/*
* Name: command
* Purpose: To input and execute a command or printable character.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Dispatch editor functions as needed.
*/
void command( window, stop )
windows *window;
int *stop;
{
int c; /* character entered */
int temp; /* temp variable */
int func;
show_line_col( window );
c = getkey( );
func = getfunc( c );
s_output( " ", g_display.mode_line, 63, g_display.mode_color );
switch (func) {
case Tab :
tab_key( window );
break;
case BackSpace :
back_space( window );
break;
case DeleteChar :
char_del_under( window );
break;
case Rturn :
insert_newline( window, TRUE, FALSE );
break;
case AddLine :
insert_newline( window, FALSE, FALSE );
break;
case SplitLine :
insert_newline( window, TRUE, TRUE );
break;
case JoinLine :
join_line( window );
break;
case DuplicateLine :
dup_line( window );
break;
case AbortCommand :
case UndoLine :
undo_line( window );
break;
case ScrollUpLine :
scroll_up( window );
break;
case ScrollDnLine :
scroll_down( window );
break;
case LineDown :
move_down( window );
break;
case LineUp :
move_up( window );
break;
case CharLeft :
move_left( window );
break;
case CharRight :
move_right( window );
break;
case ScreenDown :
page_down( window );
break;
case ScreenUp :
page_up( window );
break;
case WordRight :
word_right( window );
break;
case WordLeft :
word_left( window );
break;
case DeleteLine :
line_kill( window );
break;
case OverWrite :
g_status.insert = !g_status.insert;
show_modes( );
if (g_status.insert)
temp = g_display.insert_cursor;
else
temp = g_display.overw_cursor;
set_cursor_size( temp );
break;
case Help :
get_help( window );
break;
case RedrawScreen :
force_blank( );
redraw_screen( window );
break;
case Quit :
quit( window, stop );
break;
case Save :
save_file( window );
break;
case SaveAs :
save_as_file( window );
break;
case File :
un_copy_line( window->cursor, window, TRUE );
if (window->file_info->modified)
save_file( window );
finish( window, stop );
break;
case EditFile :
edit_another_file( window );
break;
case UnMarkBlock :
unmark_block( );
break;
case MarkBlock :
mark_block( window, BOX );
break;
case MarkLine :
mark_block( window, LINE );
break;
case MoveBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, MOVE );
break;
case DeleteBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, DELETE );
break;
case CopyBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, COPY );
break;
case KopyBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, KOPY );
break;
case FillBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, FILL );
break;
case OverlayBlock :
if (g_status.marked == TRUE)
move_copy_delete_overlay_block( window, OVERLAY );
break;
case BlockToFile :
block_write( window );
break;
case PrintBlock :
block_print( window );
break;
case BlockExpandTabs :
block_expand_tabs( window );
break;
case DelEndOfLine :
eol_kill( window );
break;
case FindForward :
find_string( window, FORWARD, TRUE );
break;
case FindBackward :
find_string( window, BACKWARD, TRUE );
break;
case RepeatFindForward :
find_string( window, FORWARD, FALSE );
break;
case RepeatFindBackward :
find_string( window, BACKWARD, FALSE );
break;
case ReplaceForward :
replace_string( window, FORWARD );
break;
case ReplaceBackward :
replace_string( window, BACKWARD );
break;
case BegOfLine :
goto_left( window );
break;
case EndOfLine :
goto_right( window );
break;
case TopOfScreen :
goto_top( window );
break;
case BotOfScreen :
goto_bottom( window );
break;
case TopOfFile :
goto_top_file( window );
break;
case EndOfFile :
goto_end_file( window );
break;
case ParenBalance :
match_pair( window );
break;
case JumpToLine :
goto_line( window );
break;
case Indent :
g_status.indent = !g_status.indent;
show_indent_mode( );
break;
case ToggleSearchCase :
if (bm.search_case == IGNORE)
bm.search_case = MATCH;
else
bm.search_case = IGNORE;
show_search_case( );
break;
case SetTabs :
set_tabstop( window->bottom_line );
break;
case NextWindow :
next_window( window );
break;
case PreviousWindow :
prev_window( window );
break;
case SplitScreen :
split_screen( window );
break;
case SizeWindow :
size_window( window );
break;
case Column_1 :
column_1( window );
break;
default :
if (c < 0x100)
insert_overwrite( window, c );
break;
}
}
/*
* Name: editor
* Purpose: Set up the editor structures and display changes as needed.
* Date: June 5, 1991
* Passed: argc: number of command line arguments
* argv: text of command line arguments
*/
void editor( argc, argv )
int argc;
char *argv[];
{
char *name; /* name of file to start editing */
windows *window; /* current active window */
windows *above; /* window above current */
windows *below; /* window below current */
file_infos *file; /* temporary file structure */
char status_line[MAX_COLS+2]; /* status line at top of window */
char *p, *q; /* for setting up status line */
int temp;
int stop;
/*
* set up the screen
*/
initialize( );
/*
* Check that user specified file to edit, if not offer help
*/
if (argc > 1)
name = argv[1];
else {
g_status.rw_name[0] = '\0';
name = g_status.rw_name;
if (get_name( "File name to edit : ", g_display.nlines, name,
g_display.text_color ) != OK)
return;
if (*name == '\0')
return;
}
edit_file( name );
if (initialize_window( ) != ERROR) {
stop = FALSE;
window = g_status.current_window;
window->file_info->dirty = FALSE;
show_window_header( window->file_info->file_name, window );
show_size_name( window );
show_size( window );
/*
* display the current window
*/
display_current_window( window );
show_modes( );
if (g_status.insert)
temp = g_display.insert_cursor;
else
temp = g_display.overw_cursor;
set_cursor_size( temp );
} else
stop = TRUE;
/*
* main loop - keep updating the display and processing any commands
* while user has not pressed stop
*/
for (; stop != TRUE;) {
window = g_status.current_window;
/*
* update all the other windows that point to file that has been changed
*/
above = below = window;
while (above->prev || below->next) {
if (above->prev) {
above = above->prev;
if (above->visible) {
file = above->file_info;
if (file->dirty == GLOBAL || file->dirty == NOT_LOCAL) {
display_current_window( above );
show_size( above );
}
}
}
if (below->next) {
below = below->next;
if (below->visible) {
file = below->file_info;
if (file->dirty == GLOBAL || file->dirty == NOT_LOCAL) {
display_current_window( below );
show_size( below );
}
}
}
}
file = window->file_info;
if (file->dirty == LOCAL || file->dirty == GLOBAL)
display_current_window( window );
file->dirty = FALSE;
/*
* all done, so position the cursor and wait for the user to enter
* something
*/
xygoto( window->ccol, window->cline );
command( window, &stop );
}
terminate( );
}